// ToolParam.cpp: implementation of the CToolParam class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "resource.h"
#include "ToolParam.h"
#include "ULCOMMDEF.h"
#include "XMLSettings.h"
#include "Utility.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CToolParam::CToolParam(LPCTSTR pszName /* = _T("") */)
{
	m_strName = pszName;
	m_nValType = VT_EMPTY;
	m_pValue = NULL;
	m_szValue = 0;
	m_lTop = INVALID_DEPTH;
	m_lBottom = INVALID_DEPTH;
	m_lSave = 0;
}

CToolParam::~CToolParam()
{
	if (m_pValue)
	{
		delete[] m_pValue;
		m_pValue = NULL;
	}
}

void CToolParam::Serialize(CXMLSettings& xml)
{
	if (xml.IsStoring())
	{
		xml.Write("Type", m_strType);
		xml.Write("Name", m_strName);
		xml.Write("Unit", m_strUnit);
		xml.Write("ValType", m_nValType);
		xml.Write("ValSize", m_szValue);
		if (m_szValue)
			xml.Write("Value", (LPBYTE)m_pValue, m_szValue);
		xml.Write("StrList", m_strArray);
		xml.Write("Top", m_lTop);
		xml.Write("Bottom", m_lBottom);
		xml.Write("Desc", m_strDesc);
		xml.Write("Print", m_bDisplayPrint);
	}
	else
	{
		xml.Read("Type", m_strType);
		xml.Read("Name", m_strName);
		xml.Read("Unit", m_strUnit);
		xml.Read("ValType", m_nValType);
		xml.Read("ValSize", m_szValue);
		if (m_nValType & VT_ARRAY)
		{
			if (m_pValue != NULL)
				delete[] m_pValue;

			m_pValue = new int(-1);
			if (m_szValue == sizeof(int))
			{
				xml.Read("Value", (LPBYTE)m_pValue, m_szValue);	
			}

			if (*(int*)m_pValue < 0)
				*(int*)m_pValue = 0;
		}
		else if (m_szValue)
		{
			if (m_pValue != NULL)
				delete[] m_pValue;
			m_pValue = new BYTE[m_szValue];
			xml.Read("Value", (LPBYTE)m_pValue, m_szValue);
		}
		xml.Read("StrList", m_strArray);
		xml.Read("Top", m_lTop);
		xml.Read("Bottom", m_lBottom);
		CString strDesc;
		xml.Read("Desc", strDesc);
		if (strDesc.GetLength())
			m_strDesc = strDesc;
		xml.Read("Print", m_bDisplayPrint);
	}
}

CString CToolParam::SetString(LPCTSTR pszText)
{
	CString strText = pszText;
	if (m_pValue == NULL)
	{
		if (m_nValType == VT_BSTR)
		{
			m_strArray[0] = pszText;
			return strText;
		}
		
		return _T("");
	}
	
	switch(m_nValType)
	{
	case VT_INT|VT_ARRAY:
		{
			int n = m_strArray.GetSize();
			int i = 0;
			for ( ; i < n; i++)
			{
				if (m_strArray[i] == pszText)
					break;
			}
			
			if (i == n)
			{
				*(int*)m_pValue = -1;
				return _T("");
			}
			
			*(int*)m_pValue = i;
			return strText;
		}
		break;
	case VT_INT:
		{
			*(int*)m_pValue = _ttoi(pszText);
			strText.Format("%d", *(int*)m_pValue);
		}
		break;
	case VT_UINT:
		{
			
			if (!SimpleScanf(pszText, "%u", m_pValue))
				*(UINT*)m_pValue = 0;
			
			strText.Format("%u", *(UINT*)m_pValue);
		}
		break;
	case VT_I2:
		{
			if (!SimpleScanf(pszText, "%sd", m_pValue))
				*(short*)m_pValue = 0;
			
			strText.Format("%hd", *(short*)m_pValue);
		}
		break;
	case VT_UI2:
		{
			if (!SimpleScanf(pszText, "%su", m_pValue))
				*(WORD*)m_pValue = 0;
			
			strText.Format("%hu", *(WORD*)m_pValue);
		}
		break;
	case VT_I4:
		{
			if (!SimpleScanf(pszText, "%ld", m_pValue))
				*(long*)m_pValue = 0;
			
			strText.Format("%ld", *(long*)m_pValue);
		}
		break;
	case VT_UI4:
		{
			
			if (!SimpleScanf(pszText, "%u", m_pValue))
				*(DWORD*)m_pValue = 0;
			
			strText.Format("%u", *(DWORD*)m_pValue);
		}
		break;
	case VT_R4:
		{
			TCHAR szVal[32];
			TCHAR* stop;
			*(float*)m_pValue = (float)_tcstod(pszText, &stop);
			_stprintf(szVal, _T("%.*g"), FLT_DIG, *(float*)m_pValue);
			strText = szVal;
		}
		break;
	case VT_R8:
		{
			TCHAR szVal[32];
			TCHAR* stop;
			*(double*)m_pValue = _tcstod(pszText, &stop);
			_stprintf(szVal, _T("%.*g"), DBL_DIG, *(double*)m_pValue);
			strText = szVal;
		}
		break;
	case VT_BYREF:
		{
			
		}
		break;
	default:
		strText = _T("------");
		break;				
	}
	
	return strText;
}

void CToolParams::Serialize(CXMLSettings& xml, BOOL bNew /* = FALSE */)
{
	if (xml.IsStoring())
	{
		POSITION pos = m_tpList.GetHeadPosition();
		for (int i = 0; pos != NULL; i++)
		{
			CToolParam* pTP = m_tpList.GetNext(pos);
		
			if (xml.CreateKey(pTP->m_strName))
			{
				pTP->Serialize(xml);
				xml.Back();
			}
		}
	}
	else
	{
		if (bNew)
		{
			CXMLNode* pCurrNode = xml.m_pCurrNode;
			m_strTool = pCurrNode->m_strName;
			POSITION pos = pCurrNode->m_lstChildren.GetHeadPosition();
			for ( ; pos != NULL; )
			{
				CXMLNode* pNode = pCurrNode->m_lstChildren.GetNext(pos);
				CToolParam* pTP = GetParam(pNode->m_strName);
				if (pTP != NULL)
				{
					xml.SetCurrNode(pNode);
					pTP->Serialize(xml);
				}
			}
			
			xml.SetCurrNode(pCurrNode);
		}
		else
		{
			CXMLNode* pCurrNode = xml.m_pCurrNode;
			m_strTool = pCurrNode->m_strName;
			POSITION pos = m_tpList.GetHeadPosition();
			for (int i = 0; pos != NULL; i++)
			{
				CToolParam* pTP = m_tpList.GetNext(pos);
				if (xml.Open(pTP->m_strName))
				{
					DWORD dwP = pTP->m_bDisplayPrint;
					pTP->Serialize(xml);
					pTP->m_bDisplayPrint = dwP;
					xml.Back();
				}
			}
		}
	}	
}

BOOL CToolParams::WriteTo(CXMLSettings& xml, long lDepth)
{
	POSITION pos = m_tpList.GetHeadPosition();
	int i;
	for (i = 0; pos != NULL; )
	{
		CToolParam* pTP = m_tpList.GetNext(pos);
		if (pTP->m_lSave > 0)
		{
			if (xml.CreateKey(pTP->m_strName))
			{
				pTP->m_lBottom = lDepth;
				pTP->Serialize(xml);
				xml.Back();
				pTP->m_lTop = lDepth;
			}
			
			InterlockedDecrement(&pTP->m_lSave);
			i++;
		}
	}

	return i;
}

BOOL CToolParams::WriteToFile(CFile* pFile)
{
	CXMLSettings xml(FALSE, m_strTool);
	Serialize(xml);
	return xml.WriteXMLToFile(pFile);
}

BOOL CToolParams::ReadFromFile(CFile* pFile)
{
	CXMLSettings xml;
	if (xml.ReadXMLFromFile(pFile))
	{
		Serialize(xml);
		return TRUE;
	}

	return FALSE;
}

BOOL CToolParams::WriteToStream(IStreamPtr& stream)
{
	CXMLSettings xml(FALSE, m_strTool);
	Serialize(xml);
	return xml.WriteXMLToStream(stream);
}

BOOL CToolParams::ReadFromStream(IStreamPtr& stream)
{
	CXMLSettings xml;
	if (xml.ReadXMLFromStream(stream))
	{
		Serialize(xml);
		return TRUE;
	}

	return FALSE;
}

CString CToolParam::GetString()
{
	if (m_nValType == VT_BSTR)
		return m_strArray[0];
	
	CString str = _T("");
	if (m_pValue == NULL)
		return str;		
	
	TCHAR szVal[32];
	switch(m_nValType)
	{
	case VT_INT|VT_ARRAY:
		{
			int i = *(int*)m_pValue;
			if ((i >= 0) && (i < m_strArray.GetSize()))
				return m_strArray[i];
		}
		break;
	case VT_INT:
		str.Format("%d", *(int*)m_pValue);
		break;
	case VT_UINT:
		str.Format("%u", *(UINT*)m_pValue);
		break;
	case VT_I2:
		str.Format("%hd", *(short*)m_pValue);
		break;
	case VT_UI2:
		str.Format("%hu", *(WORD*)m_pValue);
		break;
	case VT_I4:
		str.Format("%ld", *(long*)m_pValue);
		break;
	case VT_UI4:
		str.Format("%lu", *(DWORD*)m_pValue);
		break;
	case VT_R4:
		_stprintf(szVal, _T("%.*g"), FLT_DIG, *(float*)m_pValue);
		str = szVal;
		break;
	case VT_R8:
		_stprintf(szVal, _T("%.*g"), DBL_DIG, *(double*)m_pValue);
		str = szVal;
		break;
	case VT_BYREF:
		str.Format("%0x", (BYTE*)m_pValue);
		break;
	default:
		str = _T("------");
		break;				
	}
	
	return str;
}
